const { dbQuery } = require("../common/db");
const { CronJob } = require("cron");
const { uuid, extractErrorInfo } = require("../common/utils");

const cronCache = {}
var mainWin = null;

function showLog(msg, type) {
    mainWin.webContents.send("log", { msg: msg, type: type });
}

function addOrUpdateCronTask(crons, task) {
    var result = { success: false, error: '未知错误！' };
    try {
        var cronTasks = cronCache[task.task_id];
        // 如果已经存在相关定时任务，停止并移除
        if (cronTasks) {
            cronTasks.forEach(taskJob => {
                taskJob.stop();
            });
            showLog("停止定时任务 => " + task.task_name);
        }
        delete cronCache[task.task_id];
        cronTasks = [];
        if (crons) {
            crons.forEach(cron => {
                if (cron) {
                    console.log('启动定时器', cron, " => ", task.task_name)
                    cronTasks[cronTasks.length] = new CronJob(cron, async function () {
                        try {
                            // 标志任务为准备运行阶段
                            var res = await dbQuery("update spider_task set task_status = ?, start_datetime = NOW() where task_id = ?", [1, task.task_id])
                            if(!res.success){
                                throw new Error("标志任务为准备运行失败，" + res.error);
                            }
                            // 记录下运行记录
                            res = await dbQuery("insert into cron_run_record(record_id, task_id, cron, run_datetime, run_status) values(?, ?, ?, NOW(),?)", [uuid(), task.task_id, cron, 1]);
                            if(!res.success){
                                throw new Error("记录定时运行失败，" + res.error);
                            }
                            showLog("执行定时采集任务！ => " + task.task_name);
                        } catch (e) {
                            showLog("执行定时任务异常！ => " + task.task_name,  'error');
                            console.log("执行定时任务异常！=> " + task.task_name, e);
                            await dbQuery("insert into cron_run_record(record_id, task_id, cron, run_datetime, run_status) values(?, ?, ?, NOW(),?)", [uuid(), task.task_id, cron, 1]);
                        }
                    }, null, true, 'Asia/Chongqing');
                }
            });
        }
        cronCache[task.task_id] = cronTasks;
        result = { success: true };
    } catch (e) {
        console.log("添加更新定时任务异常！", e);
        result = { success: false, error: extractErrorInfo(e) };
    }
    return result;
}

async function initCronJob() {
    var result = { success: false, error: '未知错误！' };
    try {
        var result = await dbQuery("select * from spider_task st, spider_task_config stc where st.task_id = stc.task_id and stc.spider_crons is not null");
        if (result.success && result.data) {
            result.data.forEach(task => {
                var crons = task.spider_crons;
                crons = crons.split(/[\n]/g)
                result = addOrUpdateCronTask(crons, task);
            })
            if(result.success){
                console.log("初始化定时任务列表成功！");
            } else {
                console.log("初始化定时任务失败！" + result.error);
            }
        } else {
            console.log("加载定时任务失败！" + result.error); 
        }
    } catch (e) {
        console.log("初始化定时任务列表异常！",e )
        result = { success: false, error: extractErrorInfo(e) };
    }
    return result;
}

module.exports = {
    init: function (mainWindow) {
        mainWin = mainWindow;
        initCronJob();
    },
    initCronJob: this.initCronJob,
    loadCronJobs: async function (params) {
        var result = { success: false };
        try {
            var countResult = null;
            countResult = await dbQuery("select count(1) as count from cron_run_record");
            if (countResult.success) {
                result = await dbQuery("select crr.*, st.task_name from cron_run_record crr left join spider_task st on st.task_id = crr.task_id  order by crr.run_datetime desc limit ?,?", [params.start, params.limit]);
                if (result.success) {
                    result.total = countResult.data[0].count;
                }
            }
            return result;
        } catch (e) {
            result.error = extractErrorInfo(e);
            console.log(e)
        }
        return result;
    },
    addOrUpdateCronTask: addOrUpdateCronTask
}